package com.hernie.piggymall.auth.controller;

import com.alibaba.fastjson.TypeReference;
import com.hernie.common.constant.AuthServerConstant;
import com.hernie.common.exception.BizCodeEnume;
import com.hernie.common.utils.R;
import com.hernie.common.vo.MemberRespVo;
import com.hernie.piggymall.auth.feign.MemberFeignService;
import com.hernie.piggymall.auth.feign.ThirdPartyFeignClient;
import com.hernie.piggymall.auth.vo.UserLoginVo;
import com.hernie.piggymall.auth.vo.UserRegistVo;
import org.apache.commons.lang.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.IntFunction;
import java.util.stream.Collectors;

/**
 * @Author HuangJp
 * @Date 2022/4/8
 * @Description
 */
@Controller
public class LoginController {

    @Autowired
    private ThirdPartyFeignClient thirdPartyFeignClient;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private MemberFeignService memberFeignService;

    @ResponseBody
    @GetMapping("/sms/sendcode")
    public R sendCode(@RequestParam("phone") String phone) {
        // 防止同一个手机在60s内再次发送验证码
        String redisCode = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
        if (StringUtils.isNotBlank(redisCode)) {
            Long l = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis() - l < 60000) {
                return R.error(BizCodeEnume.SMS_CODE_EXCEPTION.getCode(), BizCodeEnume.SMS_CODE_EXCEPTION.getMsg());
            }
        }

        // TODO 接口防刷

        // 验证码的再次校验，redis 存 key-phone,value-code
        String code = UUID.randomUUID().toString().substring(0, 5);
        String codeKey = code + "_"  + System.currentTimeMillis();
        // redis 缓存验证码
        redisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone, codeKey, 10, TimeUnit.MINUTES);

        thirdPartyFeignClient.sendCode(phone, code);
        return R.ok();
    }

    /**
     *
     * TODO: 重定向携带数据：利用session原理，将数据放在session中。
     * TODO:只要跳转到下一个页面取出这个数据以后，session里面的数据就会删掉
     * TODO：分布下session问题
     * RedirectAttributes：重定向也可以保留数据，不会丢失
     * 用户注册
     * @return
     */
    @RequestMapping("/regist")
    public String regist(@Valid UserRegistVo vo, BindingResult result, Model model, RedirectAttributes redirectAttributes, HttpSession session) {
        if (result.hasErrors()) {
            Map<String, String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(fieldError -> {
                return fieldError.getField();
            }, fieldError -> {
                return fieldError.getDefaultMessage();
            }));
//            model.addAttribute("errors", errors);
            redirectAttributes.addFlashAttribute("errors", errors);
            // 校验出错，转发到注册页
//            return "reg"; // 直接转发渲染页面 ,每次刷新页面都会重复提交
//            return "forward:/reg.html";  // 转发给后台请求
            // 直接使用return "forward:/reg.html";会报错 Request method 'POST' not supported
            // 原因分析： 前端使用post请求进来  -》 转发 /reg.html(路径映射默认都是get方式访问的)


            // 重定向，获取不到Model，需要使用 RedirectAttributes 携带数据
//            return "redirect:/reg.html"; // 默认是重定向到服务器中的地址
            return "redirect:http://auth.piggymall.com/reg.html"; // 重定向到指定的地址
        }
        // 正真注册。调用远程服务进行注册
        // 1、校验验证码
        String code = vo.getCode();
        String s = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
        if (!StringUtils.isEmpty(s)) {
            if (code.equals(s.split("_")[0])) {
                // 删除验证码,令牌机制
                redisTemplate.delete(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
                // 验证码通过
                R r = memberFeignService.regist(vo);
                if (r.getCode() == 0) {
                    // 成功, 返回登录页
                    return "redirect:http://auth.piggymall.com/login.html";
                } else {
                    Map<String, String> errors = new HashMap<>();
                    errors.put("msg", r.getData("msg", new TypeReference<String>(){}));
                    redirectAttributes.addFlashAttribute("errors", errors);
                    return "redirect:http://auth.piggymall.com/reg.html";
                }

            } else {
                Map<String, String> errors = new HashMap<>();
                errors.put("code", "验证码错误");
                redirectAttributes.addFlashAttribute("errors", errors);
                // 没有验证码，返回注册页
                return "redirect:http://auth.piggymall.com/reg.html";
            }
        } else {
            Map<String, String> errors = new HashMap<>();
            errors.put("code", "验证码错误");
            redirectAttributes.addFlashAttribute("errors", errors);
            // 没有验证码，返回注册页
            return "redirect:http://auth.piggymall.com/reg.html";
        }
        // 登录成功，返回登录页
//        return "redirect:/login.html";
    }

    @PostMapping("/login")
    public String login(UserLoginVo vo, RedirectAttributes redirectAttributes, HttpSession session) {
        R r = memberFeignService.login(vo);
        if (r.getCode() == 0) {
            MemberRespVo data = r.getData("data", new TypeReference<MemberRespVo>() {
            });
            // 成功,放入session中
            session.setAttribute(AuthServerConstant.LOGIN_USER, data);
            return "redirect:http://piggymall.com";
        } else {
            Map<String, String> errors = new HashMap<>();
            errors.put("msg", r.getData("msg", new TypeReference<String>(){}));
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.piggymall.com/login.html";
        }
    }

    @GetMapping("/login.html")
    public String loginPage(HttpSession session) {
        Object attribute = session.getAttribute(AuthServerConstant.LOGIN_USER);
        if (attribute == null) {
            // 未登录
            return "login";
        } else {
            return "redirect:http//piggymall.com";
        }
    }
}
